#include "cybertron/core/logServer.hpp"
#include "cybertron/core/UtilDirectory.hpp"
#include "cybertron/core/UtilPath.hpp"
#include "cybertron/core/UtilTime.hpp"
#include "cybertron/core/SimOneServerInfo.hpp"
#include "cybertron/core/SimOneEnv.hpp"
#include "cybertron/node/StartupArguments.hpp"
#include "LogApi.hpp"
#include <fstream>
#include <codecvt>
#include <stdarg.h>
#include <string.h>

CYBERTRON_BEGIN
char* logServer::mTaskId= (char*)calloc(128,sizeof(char));
char* logServer::mProducer= (char*)calloc(16,sizeof(char));

void logServer::Initialize()
{
	//bool bRet = SimOneServerInfo::GetInstance().Init();
	bool bRet = false;
	if (bRet)
	{
		SimOneServerInfo::LogServerInfo serverInfo;
		SimOneServerInfo::GetInstance().getLogServerInfo(&serverInfo);
		setLogServerAddress(serverInfo.serverAddr.c_str(), serverInfo.port);
	}
	else
	{
		//Read environment variables of logServer
		char *logServerIp = theStartupArguments().getParamValue("LOG_SERVER_IP");//getenv("LOG_SERVER_IP");
		if (logServerIp != nullptr) {
			int logServerPort = atoi(theStartupArguments().getParamValue("LOG_SERVER_PORT"));
			setLogServerAddress(logServerIp, logServerPort);
			logOutputInfo("", "Read environment variables logServerIP:%s logServerPort:%d", logServerIp, logServerPort);
			return;
		}

		//Read configuration file of logServer
		cybertron::json jsonSensor;
		if (!JsonReader::loadFile(jsonSensor, "logOutputConfig.json"))
		{
			//logOutputInfo("", "Failed to load logOutput Config json file,use default value");
			setLogServerAddress();
			return;
		}
		else
		{
			std::string logServerIP = JsonReader::getString(jsonSensor, "LOG_SERVER_IP");
			if (logServerIP.empty())
			{
				logOutputWarn("", "LOG_SERVER_IP is empty");
				return;
			}
			int logServerPort = atoi(JsonReader::getString(jsonSensor, "LOG_SERVER_PORT").c_str());
			logOutputInfo("", "Read configuration file logServerIP:%s logServerPort:%d", logServerIP.c_str(), logServerPort);
			setLogServerAddress(logServerIP.c_str(), logServerPort);
		}
	}
}

void logServer::logServerSetup(std::string logFilePath)
{
	setLogEnableConsoleAppender();
	logServer::setLogFilePath(logFilePath.c_str());
	//SimOneEnv::GetInstance().Init();
	Initialize();
}

void logServer::setLogServerAddress(const char *logServerIp, int logServerPort)
{
	cybertron::log_enable_net_appender(logServerIp, logServerPort);
}

void logServer::setLogEnableConsoleAppender()
{
	cybertron::log_enable_console_appender();
}

void logServer::setLogFilePath(const char *logFilePath)
{
	std::string baseFilename = logFilePath;
	std::string logPath = UtilPath::combine(UtilPath::getWorkingPath(), "logServer");
	char * logPathEnv = nullptr;

	logPathEnv = getenv(CZ_LOG_PATH);

	if (logPathEnv)
		logPath = UtilPath::combine(std::string(logPathEnv), "Foundation");
	UtilDirectory::create(logPath);

	std::string filename =
		baseFilename + "_" + UtilTime::getLocalTimeStringForFile();
	filename += ".log";

	baseFilename = UtilPath::combine(logPath, filename);
	log_enable_file_appender(baseFilename.c_str());
}

void logServer::setLogTaskId(const char *taskId, const char *producer)
{
	memcpy(mTaskId, taskId, strlen(taskId));
	memcpy(mProducer, producer, strlen(producer));
}

void logOutputDebug(const char* taskId,const char *format, ...)
{
	if (format == nullptr) {
		return;
	}
	va_list ap;
	va_start(ap, format);
	char buf[1024];
	int pos = vsnprintf(buf, sizeof(buf), format, ap);
	//char *taskId = logServer::getTaskId();
	char *producer = logServer::getProducer();
	log_debug(taskId, producer, buf);
	va_end(ap);
}

void logOutputInfo(const char* taskId, const char *format, ...)
{
	if (format == nullptr) {
		return;
	}
	va_list ap;
	va_start(ap, format);
	char buf[1024];
	int pos = vsnprintf(buf, sizeof(buf), format, ap);
	//char *taskId = logServer::getTaskId();
	char *producer = logServer::getProducer();
	log_info(taskId, producer, buf);
	va_end(ap);

}

void logOutputWarn(const char* taskId, const char *format, ...)
{
	if (format == nullptr) {
		return;
	}
	va_list ap;
	va_start(ap, format);
	char buf[1024];
	int pos = vsnprintf(buf, sizeof(buf), format, ap);
	//char *taskId = logServer::getTaskId();
	char *producer = logServer::getProducer();
	log_warn(taskId, producer, buf);
	va_end(ap);

}

void logOutputError(const char* taskId, const char *format, ...)
{
	if (format == nullptr) {
		return;
	}
	va_list ap;
	va_start(ap, format);
	char buf[1024];
	int pos = vsnprintf(buf, sizeof(buf), format, ap);
	//char *taskId = logServer::getTaskId();
	char *producer = logServer::getProducer();
	log_error(taskId, producer, buf);
	va_end(ap);

}

void logOutputFatal(const char* taskId, const char *format, ...)
{
	if (format == nullptr) {
		return;
	}
	va_list ap;
	va_start(ap, format);
	char buf[1024];
	int pos = vsnprintf(buf, sizeof(buf), format, ap);
	//char *taskId = logServer::getTaskId();
	char *producer = logServer::getProducer();
	log_fatal(taskId, producer, buf);
	va_end(ap);
}
CYBERTRON_END
